/*
====================================== AUTORENDER ======================================
================================== srstclair@gmail.com =================================

Render regions in a Reaper project to separate audio files, tag them with user defined metadata, and upload via FTP.
*/

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#SingleInstance Force      
OnExit,ExitSub

;DebugStuff
UseOldMediaOnlineMethod = 0

Menu, Tray, NoStandard

;=== Init Ini File
InitIniFile()

; === INIT
SetTitleMatchMode, 2
SetKeyDelay,50,5
SetControlDelay,-1

;=== Start Log
InitLog()
AppendLog("Autorender Started")

; === Get the REAPER window ID
ReaperID := GetReaperWindowID()
detectedReaperVersion := GetReaperVersion( ReaperID )

#Include AutorenderVersion.ahk
#Include RenderControlMap.ahk
#Include Functions.ahk

If A_IsCompiled
{
	Menu, Tray, Add, Open Autohotkey Window, OpenAHK	
}
Menu, Tray, Standard

TestedReaperVersion = 3.2

;=== Set icon
If FileExist("ReaperScythe.ico")
{
	Menu,Tray,Icon,ReaperScythe.ico
}
Menu,Tray,Tip,=Autorender for Reaper=




;=== Version info tray tip
TrayTip, Autorender v%AutorenderVersion%,
(
%AutorenderDate% - Tested with Reaper %TestedReaperVersion%
Detected Reaper Version: %detectedReaperVersion%
Press Ctrl-Alt-Backspace at any time to exit.
), 5, 1        

; === Exit if no Reaper window
If !ReaperID
{
	MsgBox,262160,Open Reaper first,Autorender needs an instance of Reaper running to work...
	ExitApp
}

; === Close any render windows if they are already open
CloseRenderWindows()

; === Make sure there are no unsaved changes
CheckForUnsavedProject()

;=== Get ReaperIni
ReaperIni := GetReaperIni()

;=== Get RPP file
RPP :=GetRPP(ReaperIni)

; === If there's no valid project file, exit
If !(FileExist(RPP))
{
    MsgBox,262160,Need project file,Autorender cannot run without a valid .rpp project file.
    ExitApp
}

ProjectOffset := GetProjectOffset( RPP )

SplitPath, RPP, rppFilename
rppFilename := RegExReplace(rppFilename, "i)\.rpp")

;======================================
;Read the regions from the project file
;======================================

AppendLog("Scanning project file for regions", 1)

GetRegions(RPP)

If !RegionCount
{
	AppendLog("No regions found")
}
Else
{
	Loop %RegionCount%
	{
		AppendLog()
		AppendLog("Region ID " . Region%A_Index%_MarkerID . " found")
		AppendLog("Name: " . Region%A_Index%_Name)
		AppendLog("Start: " . Region%A_Index%_StartTime)
		AppendLog("End: " . Region%A_Index%_EndTime)
	}
}
	
;======================================================
;Read the project notes variables from the project file
;======================================================

AppendLog("Scanning project file for user variables",1)

GetUserVars(RPP)

If !UserVarCount
{
	AppendLog("No user variables found in the project notes.")
}
Else
{
	Loop %UserVarCount%
	{		
		If (UserVar%A_Index%Name = "ftpPass")
        {
            StringLen, UserVarValueLength, UserVar%A_Index%Value			
            MaskedVarValue := ""
            MaskedVarValue := StrPad(MaskedVarValue, StrLen(UserVar%A_Index%Value) ,"*")
			LogVar := UserVar%A_Index%Name . " = " . MaskedVarValue
			AppendLog(LogVar)
        }
		Else
		{
			LogVar := UserVar%A_Index%Name . " = " . UserVar%A_Index%Value
			AppendLog(LogVar)
		}
	}
}


;======================================================
;Assign vars from the stuff we got in the project notes
;======================================================

AppendLog("User variable assignment",1)

Loop %UserVarCount%
{
	
    curUserVarField := UserVar%A_Index%Name
    curUserVarValue := UserVar%A_Index%Value
	
    candidateVars = renderPath,ftpSite,ftpUser,ftpPass,ftpDir,postFTPUrl,artist,album,year,genre,comment,firstTrack,NumberOutputFiles,filenamePrefix
    Loop, parse, candidateVars, `,
    {
        If curUserVarField = %A_LoopField%
        {
            UserVar_%curUserVarField% := curUserVarValue
			
			If (curUserVarField = "ftpPass")
	        {	            
				curMaskedVarValue := ""
	            curMaskedVarValue := StrPad(curMaskedVarValue, StrLen(curUserVarValue) , "*")
                curUserVarValue := curMaskedVarValue
	        }
			LogVar = %curUserVarField% = %curUserVarValue%
			AppendLog(LogVar)
        }
    }
}

;If there's a NumberOutputFiles in the project notes, override the default ini setting
If UserVar_NumberOutputFiles !=
{
	NumberOutputFiles := UserVar_NumberOutputFiles
}


;===No regions found, ask if the whole project should be rendered
If !RegionCount
{
	AppendLog("No regions found")

	MsgBox,262180,No regions found,Do you want to automatically create a region for each item in the selected track?		
	IfMsgBox Yes
	{
		MsgBox,262180,Generate regions,Choose yes to use the items' source filename for the track name or no to enter track names manually.
		IfMsgBox Yes
		{
			HumanEditTrackNames = 0
		}
		Else
		{
			HumanEditTrackNames = 1SOng 
		}	
		AutoGenerateRegions()
		
		MsgBox,262177,Region generation complete,Press ok to save the project and restart Autorender...
		IfMsgBox OK
		{
			PostMessage,0x111,40026,,,ahk_id %ReaperID%		;Save			
			Reload
			ExitApp
		}
		Else
		{
			ExitApp
		}
	}

	MsgBox,262180,No regions found,Autorender couldn't find any regions. Should the entire project be rendered to a single file and tagged?
	IfMsgBox Yes
	{
		AppendLog("User elected to render entire project")
	    RegionCount = 1
		RenderEntire = 1
		Region1_Name := rppFilename
	}
	Else
	{
		ExitApp
	}
}


;===Default firstTrack
If !firstTrack
{
    firstTrack = 1
}

;=========================
;Show gui to edit metadata
;=========================
ShowMetadataGUI()
		
;===============
;Set render path
;===============
SetRenderPath()
StoreRenderPath()

Menu, Tray, DeleteAll
Menu, Tray, Add, Open Target Dir, OpenTargetDir
Menu, Tray, Default, Open Target Dir

Menu, Tray, NoStandard
If A_IsCompiled
{
	Menu, Tray, Add, Open Autohotkey Window, OpenAHK	
}
Menu, Tray, Standard


If !NumberOutputFiles
{
	MakeFilenamesUnique()
}

;==================
;Render the regions
;==================

AppendLog("Rendering regions",1)

;RENDER SETTTINGS
;=== Adjust render settings/confirm overwrite

WinActivate, ahk_id %ReaperID%
WinWaitActive,ahk_id %ReaperID%	
PostMessage,0x111,40015,,,ahk_id %ReaperID%           ;Open render window
WinWait,Render to file

;DISABLE CONTROLS FOR NOW
Control,Disable,,%rcButtonRender%,Render to file					;Disable render button 
Control,Disable,,%rcButtonCancel%,Render to file					;Disable cancel button 
Control,Disable,,%rcButtonQueue%,Render to file						;Disable queue button
ControlSetText,%rcEditFilename%,,Render to file						;Blank out filename
Control,Disable,,%rcEditFilename%,Render to file					;Disable filename
Control,Disable,,%rcButtonBrowse%,Render to file					;Disable browse...
Control,Disable,,%rcButtonRenderEntireProject%,Render to file		;Disable 'Render entire project' radio button
Control,Disable,,%rcButtonRenderTimeSelection%,Render to file		;Disable 'Render time selection' radio button
Control,Disable,,%rcButtonRenderCustom%,Render to file				;Disable 'Render custom' radio button
Control,Disable,,%rcEditStart%,Render to file						;Disable Start textbox
Control,Disable,,%rcEditEnd%,Render to file							;Disable End textbox
Control,Disable,,%rcEditLength%,Render to file						;Disable Length textbox
Control,Disable,,%rcComboBoxOutputFormat%,Render to file			;Disable output format list		
Control,Delete,4,%rcComboBoxOutputFormat%,Render to file			;Remove Audio Cd (bin/cue) option from output format list

;===See if user wants to adjust render settings
TrayTip, Autorender, If you need to adjust the output format settings`,`npress ESC within 5 seconds.`nPress tab to start render now., 5, 1        
Input, userAdjust, T5, {ESC}{TAB}
If ErrorLevel = EndKey:Escape
{
	TrayTip
	SetTimer, WinMoveMsgBoxStartBatchRender, 50	
	
	;=== Enable output format list		
	Control,Enable,,%rcComboBoxOutputFormat%,Render to file
	
	MsgBox,262145,Start batch render,Adjust render settings, then press ok in this window to start batch render.
	IfMsgBox Cancel
	{
		ExitApp
	}

}
TrayTip ;Clear tray tup	

;CHECK IF FILES WILL BE OVERWRITTEN
OverwriteFiles := ""
		
renderFormat := GetRenderFormat()
AppendLog("Render format: " . renderFormat)		
renderFormatExt := GetRenderFormatExt(renderFormat)
 
Loop %RegionCount%
{
	LoadCurrentRegionVars( A_Index )
	
	If FileExist( thisRegionFullPath )
	{
		OverwriteFiles = %OverwriteFiles%`n%thisRegionFullPath%
	}
}

If OverwriteFiles
{
	MsgBox,262177,Overwrite files?,If Autorender continues, the following files will be overwritten:%OverwriteFiles%
	IfMsgBox Cancel
	{
		ExitApp
	}	
}


Control,Enable,,%rcButtonRender%,Render to file	
Control,Enable,,%rcButtonCancel%,Render to file	
Control,Enable,,%rcButtonQueue%,Render to file	
Control,Enable,,%rcComboBoxOutputFormat%,Render to file
Control,Enable,,%rcEditFilename%,Render to file		
Control,Disable,,%rcButtonBrowser%,Render to file
Control,Enable,,%rcButtonRenderEntireProject%,Render to file
Control,Enable,,%rcButtonRenderTimeSelection%,Render to file
Control,Enable,,%rcButtonRenderCustom%,Render to file
Control,Enable,,%rcEditStart%,Render to file
Control,Enable,,%rcEditEnd%,Render to file
Control,Enable,,%rcEditLength%,Render to file		

;EXECUTE PSEUDO-RENDER TO SAVE SETTINGS
Fakefile = %A_WorkingDir%\Autorender_Fake_File
FileDelete,%Fakefile%*
ControlClick,%rcButtonRenderCustom%
ControlSetText,%rcEditStart%,0
ControlSetText,%rcEditEnd%,0.001
ControlSetText,%rcEditFilename%,%Fakefile%
PostMessage,0x111,1,,,Render to file	;"Click" render button

;Loop
;{
;	Sleep,500
;	IfWinExist,Finished in
;	{
;		PostMessage,0x111,1,,,Finished in	;"Click" close button
;		Break
;	}
;}

Loop
{
	Sleep,1000
	IfWinNotExist,Rendering to file
	{
		Break
	}
}

PostMessage,0x111,1,,,Finished in	;"Click" close button

FileDelete,%Fakefile%*

;Save the project to preserve the new render settings
SaveProject()

;DO PRE-REGION LOOP RENDER STUFF 
If StrLen( rcButtonQueue ) > 0 And UseRenderQueue
{
	ClearRenderQueue()
}
Else
{
	If UseOldMediaOnlineMethod
	{
		remOfflineMediaWhenInactive := KeepMediaItemsOnline()
	}
}

;RENDER THE REGIONS
Loop, %RegionCount%
{
	rNum := A_Index
	LoadCurrentRegionVars( rNum )	

	If StrLen( rcButtonQueue ) > 0 And UseRenderQueue
	{
		AddToRenderQueue( thisRegionStartRaw, thisRegionEndRaw, thisTrackNumber, thisRegionFullPath )
	}
	Else
	{
		If !RenderEntire
		{
			;=== Set the loop area to the current region	
			SetLoopRegion( thisRegionStart, thisRegionEnd )
		}
	
		WinActivate, ahk_id %ReaperID%
		WinWaitActive,ahk_id %ReaperID%	
		PostMessage,0x111,40015,,,ahk_id %ReaperID%           ;Open render window
		WinWait,Render to file
				
		curTime := TimeStamp()
		
		If RenderEntire
		{
			AppendLog("Starting Entire Project Render")
			ControlClick,%rcButtonRenderEntireProject% 	;Render entire
		}
		Else
		{
			AppendLog("Starting Region " . rNum . " - " . thisRegionStart . " to " . thisRegionEnd)
			ControlClick,%rcButtonRenderCustom%
			ControlSetText,%rcEditStart%,%thisRegionStart%
			ControlSetText,%rcEditEnd%,%thisRegionEnd%
		}
	
		ControlSetText,%rcEditFilename%,%thisRegionFullPath%
		
		If !UseOldMediaOnlineMethod
		{
			PostMessage,0x111,40101,,,ahk_id %ReaperID%		;Set all media online
			Sleep,50
		}
		
		
	   	PostMessage,0x111,1,,,Render to file	;"Click" render button
		
		Sleep, 500*SleepMultiplier
	
		;=== Deal with overwrite warning
		IfWinExist, REAPER Warning
		{
			PostMessage,0x111,1 ;OK
			If !UseOldMediaOnlineMethod
			{
				PostMessage,0x111,40101,,,ahk_id %ReaperID%		;Set all media online
			}
		}
	
		AppendLog("Region " . rNum . " rendering started")
	
		Sleep,100*SleepMultiplier	
		IfWinExist,ERROR
		{
			ExitApp
		}
	
		Sleep,200*SleepMultiplier	
		;IfWinExist,Rendering to file
		;{
			;Control,Check,,Automatically close when finished,Rendering to file
		;}
	
		Loop
		{
			Sleep,1000
			IfWinNotExist,Rendering to file
			{
				Break
			}
		}
	
		Loop
		{
			IfWinExist,Finished in
			{
				PostMessage,0x111,1,,,Finished in	;"Click" close button
				;WinKill,Finished in
			}
			Else
			{
				Break
			}	
		}
	
		AppendLog("Region " . rNum . " rendering complete")
		
		Loop
		{
			IfWinExist,Render to file
			{
				WinKill,Render to file
			}
			Else
			{
				Break
			}
		}
	}
}

;DO AFTER REGION LOOP STUFF
If StrLen( rcButtonQueue ) > 0 And UseRenderQueue
{
	;START THE QUEUE	
	PostMessage,0x111,40929,,,ahk_id %ReaperID%		;Open Queued Renders	
	WinActivate,Queued Renders
	WinWaitActive,Queued Renders	
	PostMessage,0x111,1,,,Queued Renders			;Start queued renders
	
	NoRenderWindowCount = 0
		
	Loop
	{
		Sleep,1000
		ControlGet, renderQueueLength, List, Count, SysListView321, Queued Renders
		If renderQueueLength = 0
		{
			Break
		}
	}

	Loop
	{
		IfWinExist,Queued Renders
		{
			WinKill,Queued Renders
		}
		Else
		{
			Break
		}	
	}

}
Else
{
	Loop
	{
		IfWinExist,Render to file
		{
			WinKill,Render to file
		}
		Else
		{
			Break
		}	
	}
	
	
	If UseOldMediaOnlineMethod
	{
		If remOfflineMediaWhenInactive = 1
		{
			SetMediaItemsOffline()
		}
	}

	PostMessage,0x111,40020,,,ahk_id %ReaperID%		;Clear loop selection
	PostMessage,0x111,40042,,,ahk_id %ReaperID%		;Put cursor to beginning of project
	
	;Send, {ESC}{HOME}
}

;==============
;Write mp3 tags
;==============
 
If (UserVarCount and RegExMatch( renderFormat, "(mp3|ogg|flac|monkey|wavpack)" ) )
{
	;=== Tag the audio files
	If FileExist(".\utilities\Tag.exe")
	{
		AppendLog("Tagging audio files", 1)

		Arg := ""  

		If UserVar_Album
		{
			Arg = %Arg% --album "%UserVar_album%"
		}
		Else
		{
			Arg = %Arg% --album "%rppFilename%"
		}

		If UserVar_Genre
		{
			Arg = %Arg% --genre "%UserVar_Genre%"
		}

		If UserVar_Comment
		{
			Arg = %Arg% --comment "%UserVar_Comment%"
		}

		If UserVar_Year
		{
			Arg = %Arg% --year "%UserVar_Year%"
		}
		Else
		{
			FormatTime, curYear, , yyyy
			Arg = %Arg% --year "%curYear%"
		}

		TrayTip, Autorender, Autorender is now tagging your audio files, 5, 1

		Loop, %RegionCount%
		{   			
			LoadCurrentRegionVars( A_Index )

			If ParseArtistFromRegionName
			{
				ArtistArg := thisTrackArtist
			}
			Else If UserVar_Artist
			{
				ArtistArg := UserVar_Artist
			}
			Else
			{
				ArtistArg := rppFilename
			}

			AllTags = --artist "%ArtistArg%" %Arg% --track "%thisTrackNumber%" --title "%thisRegionName%" "%thisRegionFullPath%"
			;MsgBox %AllTags%

			;=== if the file is there, tag it
			If FileExist( thisRegionFullPath )
			{
				Cmdline = .\utilities\Tag.exe %AllTags%
			}

			;===DEBUG
			;MsgBox, %Cmdline%

			AppendLog()
			RunWait %comspec% /c "%CmdLine% >> Autorender.log", , Hide
		}
		Sleep, 1000*SleepMultiplier
	}
	Else
	{
		TrayTip, Autorender, Could not find Tag.exe`nSkipping audio file tagging, 5, 2
		Sleep 1000
	}	
}

;================
;Get render label
;================

If UserVar_Artist
{
	ArtistLabelName = %UserVar_Artist%
}
Else
{
	ArtistLabelName = Unknown_Artist
}

If UserVar_Album
{
	AlbumLabelName = %UserVar_Album%
}
Else
{
	AlbumLabelName = Unknown_Album
}

curTime := TimeStamp(2)

RenderLabel = %ArtistLabelName% - %AlbumLabelName% [%curTime%]

;============
;M3U Playlist
;============

If ( CreateM3U )
{
	m3uName = %RenderLabel%.m3u
	m3uPath = %RenderPath%\%m3uName%
	
	FileDelete,%originalRenderPath%\%RenderLabel%
	
	FileAppend,#EXTM3U`n,%m3uPath%
	
	Loop, %RegionCount%
	{
		LoadCurrentRegionVars( A_Index )
		ExtraM3UInfo = #EXTINF:%thisRegionLength%,%ArtistLabelName% - %thisRegionName%
	    FileAppend,`n`n%ExtraM3UInfo%`n%thisRegionFilename%,%m3uPath%
	}		
}

;=========
;ZIP FILES
;=========
AppendLog("Zipping audio files", 1)

If ( ZipRenderedFiles )
{
	If FileExist(".\utilities\7za.exe")
	{
		
		TrayTip, Autorender, Autorender will now create a zip file of your rendered files`nPress ESC within 5 seconds to cancel, 5, 1
		
		Input, ftpCancel, T5, {ESC}
		If ErrorLevel != EndKey:Escape
		{
			zipName = %RenderLabel%.zip
			zipPath = %originalRenderPath%\%zipName%
		
		
			CmdLine = .\utilities\7za.exe a "%zipPath%"
	
			Loop, %RegionCount%
			{
				LoadCurrentRegionVars( A_Index )
			    CmdLine = %CmdLine% "%thisRegionFullPath%"
			}		
		
			If CreateM3U && FileExist( m3uPath )
			{
			    CmdLine = %CmdLine% "%m3uPath%"			
			}
			
			RunWait %comspec% /c "%CmdLine% >> Autorender.log", , Hide	
		}
		Else
		{
			AppendLog("Zipping cancelled", 1)
		}
	}
	Else
	{
		AppendLog("7za.exe not found, skipping zip file creation")
	}
}

;==============
;Upload via FTP
;==============

If (UploadFTP = 1 AND UserVar_ftpSite AND UserVar_ftpUser AND UserVar_ftpPass AND UserVar_ftpDir)
{

FileDelete Autorender.ftp

FileAppend,
(
open %UserVar_ftpSite%
%UserVar_ftpUser%
%UserVar_ftpPass%
cd %UserVar_ftpDir%
binary

), Autorender.ftp

If ArtistAlbumFolders
{
	If UserVar_Artist
	{
		createArtistDir = %UserVar_Artist%
	}
	Else
	{
		createArtistDir = Unknown Artist
	}

	If UserVar_Album
	{
		createAlbumDir = %UserVar_Album%
	}
	Else
	{
		createAlbumDir = Unknown Album
	}
	
	FileAppend, mkdir "%createArtistDir%"`n, Autorender.ftp
	FileAppend, mkdir "%createArtistDir%/%createAlbumDir%"`n, Autorender.ftp
}

If CreateM3U && FileExist( m3uPath )
{
	FileAppend, put "%m3uPath%"`n, Autorender.ftp			
}

If FileExist( zipPath )
{
	FileAppend, put "%zipPath%"`n, Autorender.ftp
}

If ArtistAlbumFolders
{
	FileAppend, cd "%createArtistDir%/%createAlbumDir%"`n, Autorender.ftp
}
	
Loop, %RegionCount%
{
	LoadCurrentRegionVars( A_Index )
    FileAppend, put "%thisRegionFullPath%"`n, Autorender.ftp
}

FileAppend,
(

ls -l
quit
), Autorender.ftp

WinWait,REAPER
TrayTip, Autorender, Autorender will now upload your files to %UserVar_ftpSite%`nPress ESC within 5 seconds to cancel, 5, 1

Input, ftpCancel, T5, {ESC}
If ErrorLevel != EndKey:Escape
{
    TrayTip
	AppendLog("Uploading files to " . UserVar_ftpSite, 1)
	AppendLog()
    RunWait %comspec% /c .\utilities\ftp.exe -s:Autorender.ftp >> Autorender.log, , Hide

    FileDelete Autorender.ftp       
	;FileDelete Autorender.zip
	
    if postFTPUrl
    {
        UrlDownloadToFile, %postFTPUrl%, postFTP.log
        FileRead, postFTPLog, postFTP.log
        FileDelete postFTP.log
        curTime := TimeStamp()
		AppendLog("postFTP results from " . postFTPUrl, 1)
		AppendLog(postFTPLog)
    }
}
Else
{
	uploadCancelled = 1
	FileDelete Autorender.ftp
	AppendLog("FTP upload cancelled")
}
;==============================
; GENERATE EMAIL HTML IF FTPED
;=============================
If (UserVar_ftpUrl and !uploadCancelled)
{
	;remove http:// if present
	UserVar_ftpUrl := RegExReplace(UserVar_ftpUrl,"^^http(s)?://")

	;trim trailing slash
	UserVar_ftpUrl := RegExReplace(UserVar_ftpUrl,"(/)*?$")
	FileDelete AutorenderEmailText.htm
	
	Title = %UserVar_Artist% %UserVar_album%
	curTime := Timestamp()
	
FileAppend,
(
<h1>MIX REPORT
<h3>%Title%</h3>
<h4>Mix time: %curTime%</h4>
), AutorenderEmailText.htm
	
	FileAppend, `n, AutorenderEmailText.htm

	If FileExist( zipPath )
	{
		EmailText = <p><a href="http://%UserVar_ftpUrl%/%zipName%">Zip File: %zipName%</a></p>
		FileAppend, %EmailText%`n, AutorenderEmailText.htm
	}
		
	Loop, %RegionCount%
	{
		LoadCurrentRegionVars( A_Index )
				
		EmailText = <p><a href="%thisTrackURL%">%thisRegionListing%</a></p>
	    FileAppend, %EmailText%`n, AutorenderEmailText.htm
	}	
	Run AutorenderEmailText.htm
}
	
}

;===
;Bye
;===

AppendLog("Autorender complete", 1)
SoundPlay, %RenderCompleteSound%
ShowFinishedGUI()
ExitApp


^!Backspace::ExitApp		;=== The killswitch shortcut (Ctrl-Alt-Backspace)
^!F5::Reload				;=== The reload shortcut (Ctrl-Alt-F5)

ExitSub:
TrayTip,Autorender,Exiting...
Sleep 1000
CloseRenderWindows()
PostMessage,0x111,40020,,,ahk_id %ReaperID%		;Clear loop selection
PostMessage,0x111,40042,,,ahk_id %ReaperID%		;Put cursor to beginning of project
PostMessage,0x111,40026,,,ahk_id %ReaperID%		;Save
SoundPlay,Nothing.mp3
ExitApp


/*
===========
Subroutines
===========
*/

WinMoveMsgBoxStartBatchRender:
SetTimer,WinMoveMsgBoxStartBatchRender, OFF
TempID:=WinExist("Start batch render")
WinGetPos,,, Width, Height, ahk_id %TempID%
WinMove, ahk_id %TempID%,, (A_ScreenWidth/2)-(Width/2), 200
Return

OpenTargetDir:
Run, %renderPath%
Return

OpenAHK:
ListLines ; shows the Autohotkey window
return